Completed
Push — master ( 3d31b2...c9ad65 )
by Sander
8s
created

angular.controller(ꞌCredentialCtrlꞌ)   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
/**
2
 * Nextcloud - passman
3
 *
4
 * @copyright Copyright (c) 2016, Sander Brand ([email protected])
5
 * @copyright Copyright (c) 2016, Marcos Zuriaga Miguel ([email protected])
6
 * @license GNU AGPL version 3 or any later version
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License as
10
 * published by the Free Software Foundation, either version 3 of the
11
 * License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU Affero General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public License
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22
23
(function () {
24
	'use strict';
25
26
27
	/**
28
	 * @ngdoc function
29
	 * @name passmanApp.controller:MainCtrl
30
	 * @description
31
	 * # MainCtrl
32
	 * Controller of the passmanApp
33
	 */
34
	angular.module('passmanApp')
35
		.controller('CredentialCtrl', ['$scope', 'VaultService', 'SettingsService', '$location', 'CredentialService',
36
			'$rootScope', 'FileService', 'EncryptService', 'TagService', '$timeout', 'NotificationService', 'CacheService', 'ShareService', 'SharingACL', '$interval', '$filter', '$routeParams', '$sce', '$translate',
37
			function ($scope, VaultService, SettingsService, $location, CredentialService, $rootScope, FileService, EncryptService, TagService, $timeout, NotificationService, CacheService, ShareService, SharingACL, $interval, $filter, $routeParams, $sce, $translate) {
38
				$scope.active_vault = VaultService.getActiveVault();
39
				if (!SettingsService.getSetting('defaultVault') || !SettingsService.getSetting('defaultVaultPass')) {
40
					if (!$scope.active_vault) {
41
						$location.path('/');
42
					}
43
				} else {
44
					if (SettingsService.getSetting('defaultVault') && SettingsService.getSetting('defaultVaultPass')) {
45
						var _vault = angular.copy(SettingsService.getSetting('defaultVault'));
46
						_vault.vaultKey = angular.copy(SettingsService.getSetting('defaultVaultPass'));
47
						VaultService.setActiveVault(_vault);
48
						$scope.active_vault = _vault;
49
						//@TODO check if vault exists
50
					}
51
				}
52
53
				$scope.show_spinner = true;
54
				var fetchCredentials = function () {
55
					VaultService.getVault({guid: $routeParams.vault_id}).then(function (vault) {
56
						var vaultKey = angular.copy($scope.active_vault.vaultKey);
57
						var _credentials = angular.copy(vault.credentials);
58
						vault.credentials = [];
59
						$scope.active_vault = vault;
60
						$scope.active_vault.vaultKey = vaultKey;
61
						VaultService.setActiveVault($scope.active_vault);
62
						for (var i = 0; i < _credentials.length; i++) {
63
							var _credential = _credentials[i];
64
							try {
65
								if (!_credential.shared_key) {
66
									_credential = CredentialService.decryptCredential(angular.copy(_credential));
67
68
								} else {
69
									var enc_key = EncryptService.decryptString(_credential.shared_key);
70
									_credential = ShareService.decryptSharedCredential(angular.copy(_credential), enc_key);
71
								}
72
								_credential.tags_raw = _credential.tags;
73
							} catch (e) {
74
75
								NotificationService.showNotification($translate.instant('error.decrypt'), 5000);
76
								//$rootScope.$broadcast('logout');
77
								//SettingsService.setSetting('defaultVaultPass', null);
78
								//.setSetting('defaultVault', null);
79
								//$location.path('/')
80
81
							}
82
							if (_credential.tags) {
83
								TagService.addTags(_credential.tags);
84
							}
85
							_credentials[i] = _credential;
86
						}
87
88
						ShareService.getCredendialsSharedWithUs(vault.guid).then(function (shared_credentials) {
89
							for (var c = 0; c < shared_credentials.length; c++) {
90
								var _shared_credential = shared_credentials[c];
91
								var decrypted_key = EncryptService.decryptString(_shared_credential.shared_key);
92
								var _shared_credential_data;
93
								try {
94
									_shared_credential_data = ShareService.decryptSharedCredential(_shared_credential.credential_data, decrypted_key);
95
								} catch (e) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
96
97
								}
98
								if (_shared_credential_data) {
99
									delete _shared_credential.credential_data;
100
									_shared_credential_data.acl = _shared_credential;
101
									_shared_credential_data.acl.permissions = new SharingACL(_shared_credential_data.acl.permissions);
102
									_shared_credential_data.tags_raw = _shared_credential_data.tags;
103
									if (_shared_credential_data.tags) {
104
										TagService.addTags(_shared_credential_data.tags);
105
									}
106
									_credentials.push(_shared_credential_data);
107
								}
108
							}
109
							angular.merge($scope.active_vault.credentials, _credentials);
110
							$scope.show_spinner = false;
111
						});
112
					});
113
				};
114
115
				var getPendingShareRequests = function () {
116
					ShareService.getPendingRequests().then(function (shareRequests) {
117
						if (shareRequests.length > 0) {
118
							$scope.incoming_share_requests = shareRequests;
119
							jQuery('.share_popup').dialog({
120
								width: 600,
121
								position: ['center', 90]
122
							});
123
						}
124
					});
125
				};
126
127
128
				var refresh_data_interval = null;
129
				if ($scope.active_vault) {
130
					$scope.$parent.selectedVault = true;
131
					fetchCredentials();
132
					getPendingShareRequests();
133
					refresh_data_interval = $interval(function () {
134
						fetchCredentials();
135
						getPendingShareRequests();
136
					}, 60000 * 5);
137
				}
138
				$scope.$on('$destroy', function () {
139
					$interval.cancel(refresh_data_interval);
140
				});
141
142
143
				$scope.permissions = new SharingACL(0);
144
145
				$scope.hasPermission = function (acl, permission) {
146
					if (acl) {
147
						var tmp = new SharingACL(acl.permission);
148
						return tmp.hasPermission(permission);
149
					} else {
150
						return true;
151
					}
152
153
				};
154
155
				$scope.acceptShareRequest = function (share_request) {
156
					var crypted_shared_key = share_request.shared_key;
157
					var private_key = EncryptService.decryptString(VaultService.getActiveVault().private_sharing_key);
158
159
					private_key = ShareService.rsaPrivateKeyFromPEM(private_key);
160
					crypted_shared_key = private_key.decrypt(forge.util.decode64(crypted_shared_key));
0 ignored issues
show
Bug introduced by
The variable forge seems to be never declared. If this is a global, consider adding a /** global: forge */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
161
					crypted_shared_key = EncryptService.encryptString(crypted_shared_key);
162
163
					ShareService.saveSharingRequest(share_request, crypted_shared_key).then(function () {
164
						var idx = $scope.incoming_share_requests.indexOf(share_request);
165
						$scope.incoming_share_requests.splice(idx, 1);
166
						var active_share_requests = false;
167
						for (var v = 0; v < $scope.incoming_share_requests.length; v++) {
168
							if ($scope.incoming_share_requests[v].target_vault_id === $scope.active_vault.vault_id) {
169
								active_share_requests = true;
170
							}
171
						}
172
						if (active_share_requests === false) {
173
							jQuery('.ui-dialog').remove();
174
							fetchCredentials();
175
						}
176
					});
177
				};
178
179
				$scope.declineShareRequest = function (share_request) {
180
					ShareService.declineSharingRequest(share_request).then(function () {
181
						var idx = $scope.incoming_share_requests.indexOf(share_request);
182
						$scope.incoming_share_requests.splice(idx, 1);
183
						var active_share_requests = false;
184
						for (var v = 0; v < $scope.incoming_share_requests.length; v++) {
185
							if ($scope.incoming_share_requests[v].target_vault_id === $scope.active_vault.vault_id) {
186
								active_share_requests = true;
187
							}
188
						}
189
						if (active_share_requests === false) {
190
							jQuery('.ui-dialog').remove();
191
							fetchCredentials();
192
						}
193
					});
194
				};
195
196
197
				var settingsLoaded = function () {
198
					$scope.settings = SettingsService.getSettings();
199
				};
200
201
				if(!SettingsService.getSetting('user_sharing_enabled')){
202
					$rootScope.$on('settings_loaded', function () {
203
						settingsLoaded();
204
					});
205
				} else {
206
					settingsLoaded();
207
				}
208
209
210
				$scope.addCredential = function () {
211
					var new_credential = CredentialService.newCredential();
212
					var enc_c = CredentialService.encryptCredential(new_credential);
213
					SettingsService.setSetting('edit_credential', enc_c);
214
					$location.path('/vault/' + $scope.active_vault.guid + '/new');
215
				};
216
217
				$scope.editCredential = function (credential) {
218
					var _credential = angular.copy(credential);
219
					$rootScope.$emit('app_menu', false);
220
					SettingsService.setSetting('edit_credential', CredentialService.encryptCredential(_credential));
221
					$location.path('/vault/' + $scope.active_vault.guid + '/edit/' + _credential.guid);
222
				};
223
224
				$scope.getRevisions = function (credential) {
225
					var _credential = angular.copy(credential);
226
					$rootScope.$emit('app_menu', false);
227
					SettingsService.setSetting('revision_credential', CredentialService.encryptCredential(_credential));
228
					$location.path('/vault/' + $scope.active_vault.guid + '/' + _credential.guid + '/revisions');
229
				};
230
231
				$scope.shareCredential = function (credential) {
232
					var _credential = angular.copy(credential);
233
					$rootScope.$emit('app_menu', false);
234
					SettingsService.setSetting('share_credential', CredentialService.encryptCredential(_credential));
235
					$location.path('/vault/' + $scope.active_vault.guid + '/' + _credential.guid + '/share');
236
				};
237
238
				var notification;
239
				$scope.deleteCredential = function (credential) {
240
					var _credential = angular.copy(credential);
241
					try {
242
						_credential = CredentialService.decryptCredential(angular.copy(credential));
243
					} catch (e) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
244
245
					}
246
					_credential.delete_time = new Date().getTime() / 1000;
247
					for (var i = 0; i < $scope.active_vault.credentials.length; i++) {
248
						if ($scope.active_vault.credentials[i].credential_id === credential.credential_id) {
249
							$scope.active_vault.credentials[i].delete_time = _credential.delete_time;
250
						}
251
					}
252
					$scope.closeSelected();
253
					if (notification) {
254
						NotificationService.hideNotification(notification);
255
					}
256
					notification = NotificationService.showNotification($translate.instant('credential.deleted'), 5000,
257
						function () {
258
							CredentialService.updateCredential(_credential).then(function (result) {
259
								if (result.delete_time > 0) {
260
									notification = false;
261
262
								}
263
							});
264
						});
265
266
				};
267
268
				$scope.recoverCredential = function (credential) {
269
					var _credential = angular.copy(credential);
270
					try {
271
						_credential = CredentialService.decryptCredential(angular.copy(credential));
272
					} catch (e) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
273
274
					}
275
					for (var i = 0; i < $scope.active_vault.credentials.length; i++) {
276
						if ($scope.active_vault.credentials[i].credential_id === credential.credential_id) {
277
							$scope.active_vault.credentials[i].delete_time = 0;
278
						}
279
					}
280
					_credential.delete_time = 0;
281
					$scope.closeSelected();
282
					if (notification) {
283
						NotificationService.hideNotification(notification);
284
					}
285
					NotificationService.showNotification($translate.instant('credential.recovered'), 5000,
286
						function () {
287
							CredentialService.updateCredential(_credential).then(function () {
288
								notification = false;
289
290
							});
291
						});
292
293
				};
294
295
				$scope.destroyCredential = function (credential) {
296
					var _credential = angular.copy(credential);
297
					CredentialService.destroyCredential(_credential.guid).then(function () {
298
						for (var i = 0; i < $scope.active_vault.credentials.length; i++) {
299
							if ($scope.active_vault.credentials[i].credential_id === credential.credential_id) {
300
								$scope.active_vault.credentials.splice(i, 1);
301
								NotificationService.showNotification($translate.instant('credential.destroyed'), 5000);
302
								break;
303
							}
304
						}
305
					});
306
				};
307
308
				$scope.view_mode = 'list'; //@TODO make this a setting
309
				$scope.switchViewMode = function (viewMode) {
310
					$scope.view_mode = viewMode;
311
				};
312
313
				$scope.filterOptions = {
314
					filterText: '',
315
					fields: ['label', 'username', 'email', 'custom_fields']
316
				};
317
318
319
				$scope.filtered_credentials = [];
320
				$scope.$watch('[selectedtags, filterOptions, delete_time, active_vault.credentials]', function () {
321
					if (!$scope.active_vault) {
322
						return;
323
					}
324
					if ($scope.active_vault.credentials) {
325
						var credentials = angular.copy($scope.active_vault.credentials);
326
						var filtered_credentials = $filter('credentialSearch')(credentials, $scope.filterOptions);
327
						filtered_credentials = $filter('tagFilter')(filtered_credentials, $scope.selectedtags);
328
						filtered_credentials = $filter('filter')(filtered_credentials, {hidden: 0});
329
						$scope.filtered_credentials = filtered_credentials;
330
					}
331
				}, true);
332
333
				$scope.selectedtags = [];
334
				var to;
335
				$rootScope.$on('selected_tags_updated', function (evt, _sTags) {
336
					var _selectedTags = [];
337
					for (var x = 0; x < _sTags.length; x++) {
338
						_selectedTags.push(_sTags[x].text);
339
					}
340
					$scope.selectedtags = _selectedTags;
341
					$timeout.cancel(to);
342
					if (_selectedTags.length > 0) {
343
						to = $timeout(function () {
344
							if ($scope.filtered_credentials) {
345
								var _filtered_tags = [];
346
								for (var i = 0; i < $scope.filtered_credentials.length; i++) {
347
									var tags = $scope.filtered_credentials[i].tags_raw;
348
									for (var x = 0; x < tags.length; x++) {
349
										var tag = tags[x].text;
350
										if (_filtered_tags.indexOf(tag) === -1) {
351
											_filtered_tags.push(tag);
352
										}
353
									}
354
								}
355
356
								$rootScope.$emit('limit_tags_in_list', _filtered_tags);
357
							}
358
						}, 50);
359
					}
360
				});
361
362
				$scope.delete_time = 0;
363
				$scope.showCredentialRow = function (credential) {
364
					if ($scope.delete_time === 0) {
365
						return credential.delete_time === 0;
366
					} else {
367
						return credential.delete_time > $scope.delete_time;
368
					}
369
370
				};
371
372
				$rootScope.$on('set_delete_time', function (event, time) {
373
					$scope.delete_time = time;
374
				});
375
376
				$scope.setDeleteTime = function (delete_time) {
377
					$scope.delete_time = delete_time;
378
				};
379
380
				$scope.selectedCredential = false;
381
				$scope.selectCredential = function (credential) {
382
					if(credential.description) {
383
						credential.description_html = $sce.trustAsHtml(angular.copy(credential.description).replace("\n", '<br />'));
384
					}
385
					$scope.selectedCredential = angular.copy(credential);
386
					$rootScope.$emit('app_menu', true);
387
				};
388
389
				$scope.closeSelected = function () {
390
					$rootScope.$emit('app_menu', false);
391
					$scope.selectedCredential = false;
392
				};
393
394
				$rootScope.$on('logout', function () {
395
					$scope.active_vault = null;
396
					$scope.credentials = [];
397
//				$scope.$parent.selectedVault = false;
398
399
				});
400
401
402
				$scope.downloadFile = function (credential, file) {
403
					var callback = function (result) {
404
						var key = null;
405
						if (!result.hasOwnProperty('file_data')) {
406
							NotificationService.showNotification($translate.instant('error.loading.file.perm'), 5000);
407
							return;
408
409
						}
410
						if (!credential.hasOwnProperty('acl') && credential.hasOwnProperty('shared_key')) {
411
							if (credential.shared_key) {
412
								key = EncryptService.decryptString(angular.copy(credential.shared_key));
413
							}
414
						}
415
						if (credential.hasOwnProperty('acl')) {
416
							key = EncryptService.decryptString(angular.copy(credential.acl.shared_key));
417
						}
418
419
						var file_data = EncryptService.decryptString(result.file_data, key);
420
						download(file_data, escapeHTML(file.filename), file.mimetype);
421
422
					};
423
424
					if (!credential.hasOwnProperty('acl')) {
425
						FileService.getFile(file).then(callback);
426
					} else {
427
						ShareService.downloadSharedFile(credential, file).then(callback);
428
					}
429
430
				};
431
432
			}]);
433
}());